package com.hwl.acl.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hwl.acl.mapper.PermissionMapper;
import com.hwl.acl.pojo.Permission;
import com.hwl.acl.pojo.RolePermission;
import com.hwl.acl.service.PermissionService;
import com.hwl.acl.service.RolePermissionService;
import com.hwl.acl.util.MenuHelper;
import com.sun.javafx.tk.PermissionHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author long
 * @since 2021-10-16
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Resource
    private RolePermissionService rolePermissionService;

    /**
     * 使用递归方法建菜单
     *
     * @param treeNodes 所有的菜单
     */
    private static List<Permission> build(List<Permission> treeNodes) {
        List<Permission> result = new ArrayList<>();

        for (Permission permission : treeNodes) {
            //获取所有的顶层菜单，设置为一级菜单
            if ("0".equals(permission.getPid())) {
                result.add(permission);
                permission.setLevel(1);
                //获取该一级菜单下所有的子菜单，也就是构建该一级菜单，并添加到最终的集合中
                permission.setChildren(findChildren(permission, treeNodes));
            }
        }
        return result;
    }

    /**
     * 递归查找子节点
     *
     * @param father    父级菜单
     * @param treeNodes 所有的菜单
     * @return 构建好的所有子菜单
     */
    private static List<Permission> findChildren(Permission father, List<Permission> treeNodes) {
        List<Permission> children = new ArrayList<>();

        for (Permission treeNode : treeNodes) {
            if (father.getId().equals(treeNode.getPid())) {
                children.add(treeNode);
                treeNode.setLevel(father.getLevel() + 1);
                treeNode.setChildren(findChildren(treeNode, treeNodes));
            }
        }
        return children;
    }

    /**
     * 使用递归方法构建菜单
     */
    @Override
    public List<Permission> queryAllMenu() {
        List<Permission> permissions = baseMapper.selectList(null);
        return build(permissions);
    }

    /**
     * 递归获取子节点
     *
     * @param id     父菜单id
     * @param idList 菜单id集合
     */
    private void selectChildListById(String id, List<String> idList) {
        //子菜单id集合
        List<String> ids = baseMapper.selectList(new QueryWrapper<Permission>().eq("pid", id))
                .stream().map(Permission::getId).collect(Collectors.toList());

        for (String cid : ids) {
            idList.add(cid);
            //继续查询该菜单下的子菜单
            this.selectChildListById(cid, idList);
        }
    }

    @Override
    public boolean removeChildById(String id) {
        //需要删除的菜单id集合
        List<String> ids = new ArrayList<>();
        //构建要删除的id集合
        this.selectChildListById(id, ids);
        ids.add(id);

        return baseMapper.deleteBatchIds(ids) == ids.size();
    }

    //另一种方法可参考分配角色
    @Override
    public boolean assignRolePermissions(String roleId, String[] permissionIds) {
        //先移除原有的权限
        rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", roleId));

        List<RolePermission> rolePermissionList = new ArrayList<>();
        for (String permissionId : permissionIds) {
            if (StringUtils.isEmpty(permissionId)) continue;

            RolePermission rolePermission = new RolePermission()
                    .setRoleId(roleId).setPermissionId(permissionId);
            rolePermissionList.add(rolePermission);
        }
        return rolePermissionService.saveBatch(rolePermissionList);
    }

    @Override
    public List<Permission> selectAllMenu(String roleId) {
        //所有权限
        List<Permission> allPermissionList = baseMapper.selectList(null);

        //根据角色id获取角色所拥有的权限id
        List<String> ids = rolePermissionService.list(new QueryWrapper<RolePermission>().eq("role_id", roleId))
                .stream().map(RolePermission::getPermissionId).collect(Collectors.toList());

        for (Permission permission : allPermissionList) {
            for (String id : ids) {
                if (id.equals(permission.getId())) {
                    permission.setIsSelect(true);
                }
            }
        }

        return build(allPermissionList);
    }

    @Override
    public List<String> selectPermissionValueByUserId(String id) {
        return baseMapper.selectPermissionValueByUserId(id);
    }

    @Override
    public List<JSONObject> selectPermissionByUserId(String id) {
        List<Permission> selectPermissionList = baseMapper.selectPermissionByUserId(id);

        List<Permission> permissionList = build(selectPermissionList);
        return MenuHelper.build(permissionList);
    }


}
